﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Ewk.Math.ComputationTypes.UnitTests
{
    [TestClass]
    public class ComputableNullUnitTests : ComputableUnitTestsBase<double>
    {
        #region Add
        [TestMethod]
        public void Computable_static_Add_with_a_null_Computable_and_a_null_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var result = Computable<double>.Add(null, null);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }

        [TestMethod]
        public void Computable_static_Add_with_a_Computable_and_a_null_Computable_returns_a_copy_of_the_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Add(one, null);

            Assert.AreEqual(one, result);
            Assert.IsFalse(ReferenceEquals(one, result));
        }

        [TestMethod]
        public void Computable_static_Add_with_a_null_Computable_and_a_Computable_returns_a_copy_of_the_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Add(null, one);

            Assert.AreEqual(one, result);
            Assert.IsFalse(ReferenceEquals(one, result));
        }
        #endregion

        #region Subtract
        [TestMethod]
        public void Computable_static_Subtract_with_a_null_Computable_and_a_null_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var result = Computable<double>.Subtract(null, null);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }

        [TestMethod]
        public void Computable_static_Subtract_with_a_Computable_and_a_null_Computable_returns_a_copy_of_the_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Subtract(one, null);

            Assert.AreEqual(one, result);
            Assert.IsFalse(ReferenceEquals(one, result));
        }

        [TestMethod]
        public void Computable_static_Subtract_with_a_null_Computable_and_a_Computable_returns_a_negate_copy_of_the_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Subtract(null, one);

            one.Multiply(-1);

            Assert.AreEqual(one, result);
            Assert.IsFalse(ReferenceEquals(one, result));
        }
        #endregion

        #region Multiply
        [TestMethod]
        public void Computable_static_Multiply_with_a_null_Computable_and_a_null_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var result = Computable<double>.Multiply(null, null);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }

        [TestMethod]
        public void Computable_static_Multiply_with_a_Computable_and_a_null_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Multiply(one, null);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }

        [TestMethod]
        public void Computable_static_Multiply_with_a_null_Computable_and_a_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Multiply(null, one);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }
        #endregion

        #region Divide
        [TestMethod]
        public void Computable_static_Divide_with_a_null_Computable_and_a_null_Computable_returns_null()
        {
            var result = Computable<double>.Divide(null, null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Computable_static_Divide_with_a_Computable_and_a_null_Computable_returns_null()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Divide(one, null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Computable_static_Divide_with_a_null_Computable_and_a_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Divide(null, one);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }
        #endregion

        [TestMethod]
        public void Computable_static_Sqrt_with_a_null_Computable_returns_a_copy_of_the_Zero_Computable()
        {
            var result = Computable<double>.Sqrt(null);
            var zero = Computable<double>.Factory.Zero;

            Assert.AreEqual(zero, result);
            Assert.IsFalse(ReferenceEquals(zero, result));
        }

        #region Pow
        [TestMethod]
        public void Computable_static_Pow_with_a_null_Computable_and_a_null_Computable_returns_null()
        {
            var result = Computable<double>.Pow(null, null);

            Assert.IsNull(result);
        }

        [TestMethod]
        public void Computable_static_Pow_with_a_Computable_and_a_null_Computable_returns_a_copy_of_the_One_Computable()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Pow(one, null);

            Assert.AreEqual(one, result);
            Assert.IsFalse(ReferenceEquals(one, result));
        }

        [TestMethod]
        public void Computable_static_Pow_with_a_null_Computable_and_a_Computable_returns_null()
        {
            var one = Computable<double>.Factory.One;
            var result = Computable<double>.Pow(null, one);

            Assert.IsNull(result);
        }
        #endregion

        #region Overloaded operators
        #region Equals
        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_true_when_two_null_Computable_values_are_compared()
        {
            var value1 = ComputableNull;
            var value2 = ComputableNull;

            Assert.IsTrue(value1 == value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_true_when_two_instances_of_Zero_Computable_are_compared()
        {
            var value1 = Computable<double>.Factory.Zero;
            var value2 = Computable<double>.Factory.Zero;

            Assert.IsFalse(ReferenceEquals(value1, value2));
            Assert.IsTrue(value1 == value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_false_when_an_instance_of_Zero_Computable_is_compared_to_null_Computable()
        {
            Assert.IsFalse(Computable<double>.Factory.Zero == ComputableNull);
        }

        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_false_when_null_Computable_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsFalse(ComputableNull == Computable<double>.Factory.Zero);
        }

        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_false_when_an_instance_of_Zero_Computable_is_compared_to_null()
        {
            Assert.IsFalse(Computable<double>.Factory.Zero == null);
        }

        [TestMethod]
        public void Computable_overloaded_operator_equal_returns_false_when_null_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsFalse(null == Computable<double>.Factory.Zero);
        }
        #endregion

        #region Smaller Than
        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_false_when_two_Computable_null_values_are_compared()
        {
            var value1 = ComputableNull;
            var value2 = ComputableNull;

            Assert.IsFalse(value1 < value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_false_when_two_instances_of_Zero_Computable_are_compared()
        {
            var value1 = Computable<double>.Factory.Zero;
            var value2 = Computable<double>.Factory.Zero;

            Assert.IsFalse(ReferenceEquals(value1, value2));
            Assert.IsFalse(value1 < value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_false_when_an_instance_of_Zero_Computable_is_compared_to_Computable_null()
        {
            Assert.IsFalse(Computable<double>.Factory.Zero < ComputableNull);
        }

        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_true_when_Computable_null_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsTrue(ComputableNull < Computable<double>.Factory.Zero);
        }

        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_false_when_an_instance_of_Zero_Computable_is_compared_to_null()
        {
            Assert.IsFalse(Computable<double>.Factory.Zero < null);
        }

        [TestMethod]
        public void Computable_overloaded_operator_smaller_than_returns_true_when_null_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsTrue(null < Computable<double>.Factory.Zero);
        }
        #endregion

        #region Greater Than
        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_false_when_two_null_values_are_compared()
        {
            var value1 = ComputableNull;
            var value2 = ComputableNull;

            Assert.IsFalse(value1 > value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_false_when_two_instances_of_Zero_Computable_are_compared()
        {
            var value1 = Computable<double>.Factory.Zero;
            var value2 = Computable<double>.Factory.Zero;

            Assert.IsFalse(ReferenceEquals(value1, value2));
            Assert.IsFalse(value1 > value2);
        }

        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_true_when_an_instance_of_Zero_Computable_is_compared_to_null()
        {
            Assert.IsTrue(Computable<double>.Factory.Zero > null);
        }

        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_false_when_null_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsFalse(null > Computable<double>.Factory.Zero);
        }

        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_true_when_an_instance_of_Zero_Computable_is_compared_to_Computable_null()
        {
            Assert.IsTrue(Computable<double>.Factory.Zero > ComputableNull);
        }

        [TestMethod]
        public void Computable_overloaded_operator_greater_than_returns_false_when_Computable_null_is_compared_to_an_instance_of_Zero_Computable()
        {
            Assert.IsFalse(ComputableNull > Computable<double>.Factory.Zero);
        }
        #endregion
        #endregion
    }
}
